﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml.Linq;
using System.Windows.Media.Imaging;

using System.IO;
using System.Configuration;

namespace VisualRibbonEditor
{
	public enum ButtonSize { Large, Small }

	/// <summary>
	/// Represents a button (or other control) on a ribbon
	/// </summary>
	public partial class RibbonButton : UserControl
	{
		public RibbonButton()
		{
			InitializeComponent();
		}

		public RibbonButton(XElement element)
		{
			InitializeComponent();

			this.SourceElement = element;

			DetermineButtonSize();

			SetImageSource();

			SetLabel();
		}

		private bool _isSelected = false;
		public bool IsSelected
		{
			get { return _isSelected; }
			set
			{
				_isSelected = value;
				if (_isSelected)
				{
					ButtonBorder.Background = new SolidColorBrush(Helpers.GetColorFromHexa("#ffedf4f4")); //light blue
					ButtonBorder.BorderBrush = new SolidColorBrush(Colors.Blue);
				}
				else
				{
					ButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
					ButtonBorder.BorderBrush = new SolidColorBrush(Colors.Transparent);
				}
			}
		}

		private ButtonSize _buttonSize = ButtonSize.Large;
		public ButtonSize Size
		{
			get{ return _buttonSize; }
			set
			{
				_buttonSize = value;
				if( _buttonSize == ButtonSize.Large)
				{
					ButtonStack.Orientation = Orientation.Vertical;
					this.MinWidth = 40;
					this.MaxWidth = 70;
					this.Height = 80;
					this.TextBlock.TextWrapping = TextWrapping.Wrap;
					this.Image.Height = 32;
					this.Image.Width = 32;
					this.Image.Margin = new Thickness(0);
					this.Margin = new Thickness(2,4,2,4);
				}
				else
				{
					//small
					ButtonStack.Orientation = Orientation.Horizontal;
					this.MinWidth = 40;
					this.MaxWidth = 250;
					this.Height = 25;
					this.TextBlock.TextWrapping = TextWrapping.NoWrap;
					this.Image.Height = 16;
					this.Image.Width = 16;
					this.Image.Margin = new Thickness(0,0,4,0);
					this.Margin = new Thickness(2,1,2,1);
					this.Image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
					this.TextBlock.VerticalAlignment = System.Windows.VerticalAlignment.Center;
					this.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
				}
			}
		}

		public XElement SourceElement { get; set; }

		private void SetImageSource()
		{
			string imageToUse = this.Size == ButtonSize.Large ? "Image32by32" : "Image16by16";
			string url = string.Empty;
			XAttribute ImageAttribute = SourceElement.Attribute(imageToUse);
			if (ImageAttribute != null)
			{
				url = ImageAttribute.Value;
			}

			if (url.StartsWith("$webresource:") && url.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
			{
				string imageName = url.Replace("$webresource:", "");
				WebResourceManager.GetWebResourceContent(imageName, bits =>
				{
					if (bits != null)
					{
						MemoryStream stream = new MemoryStream(bits);
						BitmapImage b = new BitmapImage();
						b.BeginInit();
						b.StreamSource = stream;
						b.EndInit();
						this.Image.SetValue(Image.SourceProperty, b);
					}
				});
			}
			else if (!string.IsNullOrEmpty(url))
			{
				try
				{
					BitmapImage img = new BitmapImage(new Uri(GetImageUrlAbsolute(url), UriKind.Absolute));
					this.Image.SetValue(Image.SourceProperty, img);
				}
				catch (Exception)
				{
					//swallow image not found errors
				}
			}
		}

		private string GetImageUrlAbsolute(string relativeUrl)
		{
			if (Connection.CurrentConnection.ADFSMode)
			{
				string actualURL = Connection.CurrentConnection.ServerUrl;
				if (actualURL.EndsWith("/")) { actualURL = actualURL.Substring(0, actualURL.Length - 1); }
				actualURL += relativeUrl;
				return actualURL;
			}

			if (_imagePath == null)
			{
				string path = ConfigurationManager.AppSettings["ImagePath"];
				if (!string.IsNullOrEmpty(path))
				{
					_imagePath = path;
				}
				else
				{
					_imagePath = @"..\..\Assets";
				}
			}

			Uri current = new Uri(System.AppDomain.CurrentDomain.BaseDirectory);
			Uri relative = new Uri(current, _imagePath + relativeUrl);
			return relative.ToString();
		}

		private static string _imagePath = null;

		/// <summary>
		/// Determines what size the button should be based on the TemplateAlias
		/// </summary>
		private void DetermineButtonSize()
		{
			try
			{
				string buttonTemplateAlias = SourceElement.Attribute("TemplateAlias").Value;

				//find out what template the group is using
				XElement Group = SourceElement.Ancestors("Group").FirstOrDefault();
				string groupId = Group.Attribute("Id").Value;
				string templateName = Group.Attribute("Template").Value;

				//find out which layout is the "maxsize" layout
				XElement Scaling = Group.Ancestors("Tab").Elements("Scaling").FirstOrDefault();
				XElement MaxSize = Scaling.Elements("MaxSize").Where(x => x.Attribute("GroupId").Value == groupId).FirstOrDefault();
				string groupMaxSizeLayoutTitle = MaxSize.Attribute("Size").Value;

				//get the layout
				XElement Templates = Group.Ancestors().Last().Descendants("Templates").FirstOrDefault();
				XElement GroupTemplate = Templates.Descendants("GroupTemplate").Where(x => x.Attribute("Id").Value == templateName).FirstOrDefault();
				XElement Layout = GroupTemplate.Elements("Layout").Where(x => x.Attribute("Title").Value == groupMaxSizeLayoutTitle).FirstOrDefault();

				//Find out what displayMode the templateAlias is using in the Maxsize layout
				XElement OverflowSection = Layout.Descendants()
					.Where(x => x.Attribute("TemplateAlias") != null && x.Attribute("TemplateAlias").Value == buttonTemplateAlias).FirstOrDefault();
				string displayMode = OverflowSection.Attribute("DisplayMode").Value;

				//set the size (large or small (for anything other than large))
				if (displayMode == "Large")
				{
					this.Size = ButtonSize.Large;
				}
				else
				{
					this.Size = ButtonSize.Small;
				}
			}
			catch (Exception)
			{
				this.Size = ButtonSize.Large;
			}
		}


		/// <summary>
		/// Sets the label of the button using either the specified LocLabel or
		/// just using the ID of the button if a loclable doesnt exist.
		/// </summary>
		private void SetLabel()
		{
			XAttribute LabelText = SourceElement.Attribute("LabelText");
			if (LabelText != null)
			{
				if (LabelText.Value.StartsWith("$LocLabels:"))
				{
					string id = LabelText.Value.Replace("$LocLabels:", "");
					string label = Helpers.GetLocLabelTextById(id, Connection.CurrentConnection.BaseLanguage);
					if (label != null)
					{
						TextBlock.Text = label;
						return;
					}
				}
			}

			//if no label can be found just use the id.
			string ButtonId = SourceElement.Attribute("Id").Value;
			this.TextBlock.Text = Helpers.AddSpaces(ButtonId.Substring(ButtonId.LastIndexOf(".") + 1));
		}

		/// <summary>
		/// Change color on hover.
		/// </summary>
		private void UserControl_MouseEnter(object sender, MouseEventArgs e)
		{
			if (!_isSelected)
			{
				ButtonBorder.Background = new SolidColorBrush(Helpers.GetColorFromHexa("#ffedf4f4")); //light blue
			}
		}

		/// <summary>
		/// Change color back on mouseleave
		/// </summary>
		private void UserControl_MouseLeave(object sender, MouseEventArgs e)
		{
			if (!_isSelected)
			{
				ButtonBorder.Background = new SolidColorBrush(Colors.Transparent);
			}
		}

	}
}
